#include "CRenderQueueSorter.h"
#include "IRenderable.h"
#include "DataManager.h"
#include "IVertexBuffer.h"
#include "IEffect.h"
#include "IRenderTarget.h"

															/// RENDER LIST
															/// RENDER LIST
															/// RENDER LIST

/// Render List Constructor
/**	@param renderable - renderable of the rendering list */
CRenderList::CRenderList( IRenderable* renderable ) : m_pRenderable(renderable) {
}

/// Render List Destructor
CRenderList::~CRenderList( ) {
}

/// Process the render list
/**	@param rt - render target to render to */
void CRenderList::Process( IRenderTarget* rt ) {
	// Set the vertex and index sources
	IVertexBuffer* geometry;
	IVertexBuffer* indices;
	if( m_pRenderable->GetGeometry( ) ) {
		geometry = (IVertexBuffer*) 	m_pRenderable->GetRepository( )->Get( m_pRenderable->GetGeometry( ) );
		geometry->Bind( );
	} else return;
	if( m_pRenderable->GetIndices( ) ) {
		indices  = (IVertexBuffer*) 	m_pRenderable->GetRepository( )->Get( m_pRenderable->GetIndices( ) );
		indices->Bind( );
	}
	// Apply effect
	if( m_pRenderable->GetEffect( ) ) {
		IEffect* effect 			= (IEffect*) 			m_pRenderable->GetRepository( )->Get( m_pRenderable->GetEffect( ) );
		effect->Bind( );
	}

	// Render all instances of this data
	for( uint it = 0; it < m_vecRawRenderList.size(); it++ ) {
		rt->SetTransform( m_vecRawRenderList[it] );
		geometry->DrawIndexed( indices );
	}
}

/// Process the render list, but just render geometry. No render state or effects apply while using this routine
/**	@param rt - render target to render to */
void CRenderList::ProcessGeometryOnly( IRenderTarget* rt ) {
	// Set the vertex and index sources
	IVertexBuffer* geometry;
	IVertexBuffer* indices;
	if( m_pRenderable->GetGeometry( ) ) {
		geometry = (IVertexBuffer*) 	m_pRenderable->GetRepository( )->Get( m_pRenderable->GetGeometry( ) );
		geometry->Bind( );
	} else return;
	if( m_pRenderable->GetIndices( ) ) {
		indices  = (IVertexBuffer*) 	m_pRenderable->GetRepository( )->Get( m_pRenderable->GetIndices( ) );
		indices->Bind( );
	}

	// Render all instances of this data
	for( uint it = 0; it < m_vecRawRenderList.size(); it++ ) {
		rt->SetTransform( m_vecRawRenderList[it] );
		geometry->DrawIndexed( indices );
	}
}

/// Insert item into the render list
/**	@param object - instance to insert */
void CRenderList::Insert( IInstance* instance ) {
	m_vecRawRenderList.push_back( instance );
}

/// Clear the render list
void CRenderList::Clear( ) {
	m_vecRawRenderList.clear( );
}

/// Sort the render list
void CRenderList::Sort( ) {
	//TODO std::sort(m_vecRawRenderList.begin(), m_vecRawRenderList.end() );
}



															/// RENDER QUEUE SORTER
															/// RENDER QUEUE SORTER
															/// RENDER QUEUE SORTER

/// Render queue constructor
CRenderQueueSorter::CRenderQueueSorter( ) {
}

/// Render queue destructor
CRenderQueueSorter::~CRenderQueueSorter( ) {
}

/// Process the render queue. All data is cleared after this is done.
/**	@param rt - render target to render to */
void	CRenderQueueSorter::Process( IRenderTarget* rt ) {
	ProcessAndKeep( rt );
	Clear( );
}

/// Process the render queue. All data is kept after this procedure
/**	@param rt - render target to render to */
void	CRenderQueueSorter::ProcessAndKeep( IRenderTarget* rt ) {
	uint it = 0;
	while( it < m_vecRawScene.size() ) {
		m_vecRawScene[it].Process( rt );
		it++;
	}
}

/// Insert item into queue
/**	@param instance - the transformation
   	@param model - renderable element */
void	CRenderQueueSorter::Enqueue( IInstance* instance, IRenderable* model ) {
	switch( model->GetType( ) ) {
		//TODO More renderable types integrated here
		default: {
			CRenderList rendlist = CRenderList( model );
			rendlist.Insert( instance );
			m_vecRawScene.push_back( rendlist );
			break;}
	}
}

/// Insert item into queue
/**	@param instance - the transformation */
void	CRenderQueueSorter::Enqueue( IInstance* instance ) {
	//TODO Get renderable from instance data handle
	/*
	switch( model->GetType( ) ) {
		//TODO More renderable types integrated here
		default: {
			CRenderList rendlist = CRenderList( model );
			rendlist.Insert( instance );
			m_vecRawScene.push_back( rendlist );
			break;}
	}
	*/
}

/// Insert item into queue
/**	@param model - renderable element */
void	CRenderQueueSorter::Enqueue( IRenderable* model ) {
	//TODO Get instance from renderable data handle
	/*
	switch( model->GetType( ) ) {
		//TODO More renderable types integrated here
		default: {
			CRenderList rendlist = CRenderList( model );
			rendlist.Insert( instance );
			m_vecRawScene.push_back( rendlist );
			break;}
	}
	*/
}

/// Clear the render queue
void	CRenderQueueSorter::Clear( ) {
	m_vecRawScene.clear( );
}

/// Sort the render queue
void	CRenderQueueSorter::Sort( ) {
	//TODO std::sort( m_vecRawScene.begin( ), m_vecRawScene.end( ) );
}

